﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace M3G {

    public class Blender : Object3D {

        #region Constant
        // チャンネル
        public const int SrcColor              = 114;
        public const int SrcAlpha              = 116;
        public const int DstAlpha              = 118;
        public const int DstColor              = 120;

        // BlendFunction
        public const int Add                   = 88;
        public const int Subtract              = 89;
        public const int ReverseSubtract       = 90;

        // BlendFactor
        public const int Zero                  = 112;
        public const int One                   = 113;
        public const int OneMinusSrcColor      = 115;
        public const int OneMinusSrcAlpha      = 117;
        public const int OneMinusDstAlpha      = 119;
        public const int OneMinusDstColor      = 121;
        public const int SrcAlphaSaturate      = 122;
        public const int ConstantColor         = 123;
        public const int OneMinusConstantColor = 124;
        public const int ConstantAlpha         = 125;
        public const int OneMinusConstantAlpha = 126;
        #endregion

        #region Field
        Dictionary<int,int> blendFunctions;
        Dictionary<int,int> blendFactors;
        uint                blendColor;
        #endregion

        #region Method
        public Blender () {
            this.blendFunctions = new Dictionary<int, int> ();
            this.blendFunctions.Add (Blender.SrcColor, Blender.Add);
            this.blendFunctions.Add (Blender.SrcAlpha, Blender.Add);

            this.blendFactors = new Dictionary<int, int> ();
            this.blendFactors.Add (Blender.SrcColor, Blender.One);
            this.blendFactors.Add (Blender.SrcAlpha, Blender.One);
            this.blendFactors.Add (Blender.DstColor, Blender.Zero);
            this.blendFactors.Add (Blender.DstAlpha, Blender.Zero);

            this.blendColor = 0x00000000u;
        }

        protected Blender (Blender blender)
            : base (blender) {
            this.blendFunctions = new Dictionary<int, int> (blender.blendFunctions);
            this.blendFactors = new Dictionary<int, int> (blender.BlendFactor);
            this.blendColor = blender.blendColor;
        }


        public uint BlendColor {
            get { return blendColor; }
            set { blendColor = value; }
        }

        public Dictionary<int, int> BlendFunction {
            get {
                return new Dictionary<int, int> (blendFunctions);
            }
        }

        public Dictionary<int, int> BlendFactor {
            get {
                return new Dictionary<int, int> (blendFactors);
            }
        }

        public void SetBlendFactors (int srcColor, int srcAlpha, int dstColor, int dstAlpha) {
            if (srcColor < Blender.Zero || srcColor > Blender.OneMinusConstantAlpha ||
                srcAlpha < Blender.Zero || srcAlpha > Blender.OneMinusConstantAlpha ||
                dstColor < Blender.Zero || dstColor > Blender.OneMinusConstantAlpha ||
                dstAlpha < Blender.Zero || dstAlpha > Blender.OneMinusConstantAlpha ||
                dstColor == Blender.SrcAlphaSaturate || dstAlpha == Blender.SrcAlphaSaturate) {
                throw new ArgumentException ("Blend factors are invalid, see JSR-297");
            }

            this.blendFactors[Blender.SrcColor] = srcColor;
            this.blendFactors[Blender.SrcAlpha] = srcAlpha;
            this.blendFactors[Blender.DstColor] = dstColor;
            this.blendFactors[Blender.DstAlpha] = dstAlpha;
        }

        public void SetBlendFunctions (int funcColor, int funcAlpha) {
            if ((funcColor != Blender.Add && funcColor != Blender.Subtract && funcColor != Blender.ReverseSubtract) ||
                (funcAlpha != Blender.Add && funcAlpha != Blender.Subtract && funcAlpha != Blender.ReverseSubtract)) {
                throw new ArgumentException ("Blend functions must be Add,Subtract,ReverseSubtract, color=" + funcColor + ",alpha=" + funcAlpha);
            }

            this.blendFunctions[Blender.SrcColor] = funcColor;
            this.blendFunctions[Blender.SrcAlpha] = funcAlpha;
        }

        public override Object3D Duplicate () {
            return new Blender (this);
        }

        #endregion

    }
}
